package emulator.hardware.io.peripherals.iec;

import java.io.File;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.HashMap;

import emulator.cbm.Petscii;

public class FsDirectory
{
	String current_path = null;
	HashMap<String, DirEntry> directory_map = new HashMap<String, DirEntry>(); 	
	
	public void load(String path)
	{
		unload();
		
		File dir = new File(path);
		if (dir.isDirectory())
		{
			current_path = dir.getAbsolutePath();
			
			File[] dir_entries = dir.listFiles();
			for (File entry : dir_entries)
			{
				DirEntry dir_entry = new DirEntry(entry);
				while (directory_map.containsKey(dir_entry.getCbmName()))
					dir_entry.mutateCbmName();
				directory_map.put(dir_entry.getCbmName(), dir_entry);
			}
		}
	}
	
	public void unload()
	{
		current_path = null;
		directory_map.clear();
	}
	
	public void getDirectory(ByteBuffer buffer)
	{
		buffer.clear();
		buffer.order(ByteOrder.LITTLE_ENDIAN);
		if (current_path != null)
		{
			readAddress(buffer);
			readTitle(buffer);
			for (DirEntry dir_entry : directory_map.values())
			{
				dir_entry.read(buffer);
			}
			readEof(buffer);
		}
	}

	private void readEof(ByteBuffer buffer) {
		buffer.putShort((short) 0);
	}

	private void readAddress(ByteBuffer buffer) {
		buffer.putShort((short) 0x0401);
	}

	private void readTitle(ByteBuffer buffer) {
		buffer.putShort((short) 0x0101); // link
		buffer.putShort((short) 0); // blocks = 0
		buffer.put((byte) 0x12); // RVS ON
		putBufferString(buffer, current_path, 16);
		buffer.put((byte) ' ');
		buffer.put("SFS".getBytes());
		buffer.put((byte) 0);	// EOL
	}

	private void putBufferString(ByteBuffer buffer, String string, int len) 
	{
		buffer.put((byte)'"');
		char[] schars = string.toCharArray();
		int i = 0;
		for (;i<len;i++)
		{
			if (i >= schars.length)
				break;
			buffer.put(Petscii.asc2pet(schars[i]));
		}
		buffer.put((byte)'"');
		for (;i<len;i++)
		{
			buffer.put((byte)' ');
		}
	}

	public String getFilePath(String cbm_name) {
		DirEntry entry = directory_map.get(Petscii.pet2asc(cbm_name));
		return (entry != null ? current_path + File.separator + entry.getFullName() : null);
	}
	
	class DirEntry
	{
		private String full_name;
		private String cbm_name;
		private String type;
		private int blocks;
		
		public DirEntry(File entry)
		{
			full_name = entry.getName();
			cbm_name = (full_name.length() > 16 ? full_name.substring(0, 16) : full_name);
			if (entry.isDirectory())
			{
				type = "DIR";
				blocks = 0;
			}
			else
			{
				type = "PRG";
				blocks = (int)(entry.length()+255)/256;
				if (blocks > 0x7fff)
					blocks = 0x7fff;
			}
		}
		
		public void read(ByteBuffer buffer) {
			buffer.putShort((short) 0x0101); // link
			buffer.putShort((short) getBlocks());
			if (getBlocks() < 1000)
			{
				buffer.put((byte)' ');
				if (getBlocks() < 100)
				{
					buffer.put((byte)' ');
					if (getBlocks() < 10)
						buffer.put((byte)' ');
				}
			}
			putBufferString(buffer, getCbmName(), 16);
			buffer.put((byte) ' ');
			buffer.put(type.getBytes());
			buffer.put((byte) 0);	// EOL
		}

		public void mutateCbmName() {
			char[] name = cbm_name.toCharArray();
			for (int index = 15; index > 0; index--)
			{
				if (name[index] < 126)
				{
					name[index]++;
					cbm_name = new String(name);
					return;
				}
				name[index] = '0';
			}
		}

		public String getFullName() { return full_name; }
		public String getCbmName() { return cbm_name; }
		public String getType() { return type; }
		public int getBlocks() { return blocks; }
	}
}
